#pragma ident "$Id: Ambiguity.hpp  $"

/**
 * @file Ambiguity.hpp
 * Class to define and handle the edge of the 'observed' network.
 */

#ifndef GPSTK_AMBIGUITY_HPP
#define GPSTK_AMBIGUITY_HPP

//============================================================================
//
//  Function 
//
//  store the ambiguity 
//   
//  Copyright
//  all rights reserved by Shoujian Zhang
//
//  History
//
//  2011/12/08
//      Create this program, 
//      Change the type of the arc source from "SourceID" to "Vertex",
//      Change the type of the arc satellite from "SatID" to "vertex".
//      It will be useful in the Kruskal algorithm to create minmum spanning tree.
//  2012/06/15
//      remove the arcNumber from this class
//  2019/09/19
//      add ambiArc for this class
//
//============================================================================

#include <set>
#include <map>
#include <list>
#include <queue>
#include <vector>

#include "Exception.hpp"
#include "Vertex.hpp"
#include "SatID.hpp"
#include "StringUtils.hpp"
#include "SatID.hpp"
#include "SourceID.hpp"
#include "Variable.hpp"

using namespace gpstk::StringUtils;

namespace gpstk
{

      /** @addtogroup DataStructures */
      //@{
      
      /**
       *  Class to store the ambi information for the observed edge, including
       *  the receiver's Source name, Satellite, and ambi number.
       */
   class Ambiguity
   {
   public:

         /**
          * @ingroup exceptionclass
          * DayTime basic exception class.
          */
      NEW_EXCEPTION_CLASS(AmbiguityException, gpstk::Exception);


         /// Default constructor for Ambiguity
      Ambiguity()
      {};


         /** Common constructor for Ambiguity.
          *
          * @param source     Source this Ambiguity is related to.
          * @param sat        Satellite this Ambiguity is related to.
          * @param weight     Variable representing the independent term.
          */
      Ambiguity( const SourceID source,
                 const SatID sat,
                 const double arc,
                 TypeID type)
          : ambiSource(source), ambiSat(sat), ambiArc(arc), ambiType(type) 
      {};

         /// Common constructor for Ambiguity.
      Ambiguity( const Variable& var)
      {
          ambiSource = var.getSource();
          ambiSat = var.getSatellite();
          ambiArc = var.getArc();
          ambiType = var.getType();
      };


      //////////////////////
         /// Copy constructor.
      Ambiguity(const Ambiguity &amb)
         noexcept(false);


         /// Assignment operator.
      Ambiguity& operator=(const Ambiguity& right)
         throw();


         /// Get source this variable is assigned to (if any).
      SourceID getSource() const
      { return ambiSource; };


         /** Set source this variable is assigned to.
          *
          * @param source     Internal, specific SourceID of variable.
          */
      Ambiguity& setSource(const SourceID& source)
      { ambiSource = source; return (*this); };



         /// Get satellite this variable is assigned to (if any).
      SatID getSatellite() const
      { return ambiSat; };


         /** Set satellite this variable is assigned to.
          *
          * @param sat   Internal, specific SatID of variable.
          */
      Ambiguity& setSatellite(const SatID& sat)
      { ambiSat= sat; return (*this); };

      double getArc() const
      { return ambiArc; };

      Ambiguity& setArc(const double& arc)
      { ambiArc = arc; return (*this); };


      TypeID getType() const
      { return ambiType; }


      Ambiguity& setType(const TypeID& type)
      { ambiType = type; return (*this); };


         /// This ordering is required to be able
         /// to use a Ambiguity as an index to a std::map, or as part of a
         /// std::set.
      virtual bool operator<(const Ambiguity& right) const;


         /// Equality operator
      virtual bool operator==(const Ambiguity& right) const;


         /// Destructor
      virtual ~Ambiguity() {};


   protected:


         /// satellite of this ambi.
      SatID ambiSat;

         /// source of this ambi.
      SourceID ambiSource;

      TypeID ambiType;

         /// source of this ambi.
      double ambiArc;


   }; // End of class 'Ambiguity'

   inline std::ostream& operator<<( std::ostream& s,
                             const Ambiguity& ambi )
   {
      
     SatID rinSat(ambi.getSatellite());
      s << ambi.getSource() << " "
        << rinSat << " " 
        << rightJustify(asString(int(ambi.getArc())),4) << " " 
        ;

      return s;
   };

      /// Handy type definition

   typedef std::set<Ambiguity> AmbiguitySet;
   typedef std::map<Ambiguity, double> AmbiguityDataMap;

      //@}

}  // End of namespace gpstk
#endif   // GPSTK_ARC_HPP
